package com.hzchendou.blog.demo.resource.security.filter;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.hzchendou.blog.demo.common.model.BlogAuthentication;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * 安全验证Token过滤器
 *
 * @Date: 2022-06-06 11:31
 * @since: 1.0
 */
public class SecurityAuthTokenFilter extends OncePerRequestFilter {

    private static final String AUTH_TOKEN_NAME = "token";


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(AUTH_TOKEN_NAME);
        if (StringUtils.isEmpty(token)) {
            /// 继续处理
            filterChain.doFilter(request, response);
            return;
        }
        String json = new String(Base64.getDecoder().decode(token), StandardCharsets.UTF_8);
        JSONObject tokenJson = JSONObject.parseObject(json);
        List<String> resourceIds = new ArrayList<>();
        if (tokenJson.containsKey("aud")) {
            JSONArray auds = tokenJson.getJSONArray("aud");
            if (!auds.isEmpty()) {
                resourceIds.addAll(auds.toList(String.class));
            }
        }
        String userId = tokenJson.getString("user_name");
        String clientId = tokenJson.getString("client_id");
        List<GrantedAuthority> authorities = new ArrayList<>();
        if (tokenJson.containsKey("authorities")) {
            JSONArray authors = tokenJson.getJSONArray("authorities");
            if (!authors.isEmpty()) {
                authorities.addAll(authors.toList(String.class).stream()
                        .map(SimpleGrantedAuthority::new).collect(
                                Collectors.toList()));
            }
        }
        BlogAuthentication authentication = new BlogAuthentication(userId, clientId, authorities);
        authentication.setResourceIds(resourceIds);
        List<String> scopes = new ArrayList<>();
        if (tokenJson.containsKey("scope")) {
            JSONArray scs = tokenJson.getJSONArray("scope");
            if (!scs.isEmpty()) {
                scopes.addAll(scs.toList(String.class));
            }
        }
        authentication.setScops(scopes);
        if (tokenJson.containsKey("exp")) {
            JSONObject expJson = tokenJson.getJSONObject("exp");
            if (expJson.containsKey("epochSecond")) {
                authentication.setExp(expJson.getLong("epochSecond") * 1000L);
            }
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(request, response);
    }
}
